﻿using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Inscriptionem.Extensions;
using Inscriptionem.Localization;

namespace Inscriptionem.MVC
{
    public class RegexRoute : Route
    {
        private readonly Regex _regEx;
        private readonly RouteValueDictionary _defaultValues;

        public RegexRoute(string pattern, object defaultValues)
            : this(pattern, new RouteValueDictionary(defaultValues))
        { }

        public RegexRoute(string pattern, RouteValueDictionary defaultValues)
            : this(pattern, defaultValues, new MvcRouteHandler())
        { }

        public RegexRoute(string pattern, RouteValueDictionary defaultValues, IRouteHandler routeHandler)
            : base(null, routeHandler)
        {
            this._regEx = new Regex(pattern);
            this._defaultValues = defaultValues;
        }

        private void AddDefaultValues(RouteData routeData)
        {
            if (this._defaultValues != null)
            {
                foreach (KeyValuePair<string, object> pair in this._defaultValues)
                {
                    routeData.Values[pair.Key] = pair.Value;
                }
            }
        }

        public string[] Namespaces { get; set; }

        public override RouteData GetRouteData(HttpContextBase httpContext)
        {
            string requestedUrl = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo;
            Match match = _regEx.Match(requestedUrl);
            
            if (match.Success)
            {
                RouteData routeData = new RouteData(this, this.RouteHandler);
                AddDefaultValues(routeData);
                
                for (int i = 0; i < match.Groups.Count; i++)
                {
                    string key = _regEx.GroupNameFromNumber(i);
                    if (!key.IsNumeric())
                    {
                        Group group = match.Groups[i];
                        if (!string.IsNullOrWhiteSpace(key) && !string.IsNullOrWhiteSpace(group.Value))
                        {
                            if (key == "language")
                            {
                                if (group.Value.ToLower().ContainsAny(Language.AllowedValues.Select(l => l.Name.ToLower())))
                                {
                                    routeData.Values[key] = group.Value;
                                }
                                else
                                {
                                    routeData.Values["section"] = group.Value;
                                }
                            }
                            else
                            {
                                routeData.Values[key] = group.Value;
                            }
                        }
                    }
                }

                if (Namespaces != null && Namespaces.Length != 0)
                {
                    routeData.DataTokens.Add("namespaces", Namespaces);
                }

                return routeData;
            }

            return null;
        }
    }
}